<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
	<TITLE></TITLE>
	<META NAME="GENERATOR" CONTENT="LibreOffice 3.5  (Linux)">
	<META NAME="AUTHOR" CONTENT="Viacheslav Naydenov">
	<META NAME="CREATED" CONTENT="20130519;18341600">
	<META NAME="CHANGEDBY" CONTENT="Viacheslav Naydenov">
	<META NAME="CHANGED" CONTENT="20130519;18345000">
	<STYLE TYPE="text/css">
	<!--
		@page { size: 21cm 29.7cm; margin: 2cm }
		P { margin-bottom: 0.21cm }
		H2 { margin-bottom: 0.21cm; page-break-after: avoid }
		H2.western { font-family: "Times New Roman", serif; font-size: 18pt; font-weight: bold }
		H2.cjk { font-family: "Droid Sans Fallback"; font-size: 18pt; font-weight: bold }
		H2.ctl { font-family: "Lohit Hindi"; font-size: 18pt; font-weight: bold }
		TT.western { font-family: "Droid Sans Mono", monospace }
		TT.cjk { font-family: "Droid Sans Fallback", monospace }
		TT.ctl { font-family: "Lohit Hindi", monospace }
	-->
	</STYLE>
</HEAD>
<BODY LANG="ru-RU" LINK="#000080" VLINK="#800000" DIR="LTR">
<H2 CLASS="western">Реализация отношения «1 к n»</H2>
<P>Изложу мою точку зрения на то, каким
образом можно реализовать отображение
отношения «1 к n». Сторона «1» - главная
таблица, в то время как сторона «n»
соответствует подчинённой (дочерней)
таблице. Предположим, что нам хочется
уметь манипулировать отношением с обеих
сторон. С подчинённой стороны это
отношение будет выглядеть как
свойство-объект, и этот связанный объект,
вероятно, можно устанавливать/менять/очищать.
Со стороны главной таблицы то же отношение
будет выглядеть как некое свойство-коллекция,
которая позволяет по ней
итерировать/добавлять/удалять ссылки
на объекты. Так как любые изменения,
сделанные с одной стороны, должны
немедленно стать доступны с другой
стороны этого отношения, то мы имеем
следующие возможности достичь этого: 
</P>
<UL>
	<LI><P STYLE="margin-bottom: 0cm">Проталкивать изменения
	всем участникам данного отношения
	немедленно. В этом случае свойство-коллекция,
	о котором уже говорилось, можно было
	бы реализовать на основе контейнеров
	общего назначения, переопределив методы
	для модификации контейнера. 
	</P>
	<LI><P>Можно ввести промежуточный объект
	«экземпляр отношения», который будет
	владеть всей информацией о данном
	отношении для ровно одного экземпляра
	главной сущности. Тогда все запросы к
	свойствам с любой стороны отношения
	будут доставать данные из этого
	промежуточного объекта. 
	</P>
</UL>
<P>Чтобы выбрать между этими способами
нужно ответить на несколько важных
вопросов: 
</P>
<UL>
	<LI><P STYLE="margin-bottom: 0cm">Как будут создаваться
	экземпляры отображаемых классов? Можно
	ли создать экземпляр отдельно без
	вставки его в реестр <TT CLASS="western">IdentityMap</TT>?
	Как насчёт создания связной структуры
	из новых объектов? 
	</P>
	<LI><P STYLE="margin-bottom: 0cm">Можно ли копировать
	экземпляры отображённых классов, при
	этом сохраняя знание о других экземплярах,
	чтобы потом иметь возможность протолкнуть
	изменения? Или может быть нам следует
	иметь единственный экземпляр для каждой
	записи? 
	</P>
	<LI><P>Кто отвечает за удаление объектов
	во всех возможных сценариях? 
	</P>
</UL>
<P>В любом случае есть механизмы, которые
обычно используются в любом ORM-подобном
решении. Например, паттерн <TT CLASS="western">IdentityMap</TT>
подразумевает, что все экземпляры
отображённых классов, изменения которых
должны попасть в БД, следует регистрировать
в специальном реестре. Это требуется
для последующей операции «flush». Конечно,
требуется поддерживать статус записей.
По моему мнению, подход «экземпляр
отношения» несколько легче реализовать.
В частности, можете взглянуть на файлы
<TT CLASS="western">DataObject.h</TT>, <TT CLASS="western">DataObject.cpp</TT>
и тесты в файле <TT CLASS="western">TestDataObject.cpp</TT>
(папка <TT CLASS="western">lib/orm/</TT>). Библиотека
YB.ORM использует динамически типизированные
объекты внутри и статически типизированные
«тонкие» обёртки снаружи. Класс <TT CLASS="western">DataObject</TT>
представляет экземпляр отображённого
класса, где отображение задаётся в
описании метаданных. Подобные объекты
всегда выделяются в куче и не копируются.
Они хранят значения данных. У них есть
ссылка на метаданные для отображаемой
таблицы. Конечно, внутри таких объектов
поддерживается статус, один из: <TT CLASS="western">New</TT>
(вновь созданный), <TT CLASS="western">Ghost</TT>
(объект не загружен, есть лишь его ID),
<TT CLASS="western">Dirty</TT> (в загруженный объект
внесены изменения), <TT CLASS="western">Sync</TT>
(объект загружен, изменений не было),
<TT CLASS="western">ToBeDeleted</TT> (помечен на удаление),
<TT CLASS="western">Deleted</TT> (объект удалён). Чтобы
поддержать отношений, в которых данный
объект участвует в качестве стороны
«n» у каждого объекта есть множество
указателей на экземпляры <TT CLASS="western">RelationObject</TT>
(поле <TT CLASS="western">slave_relations_</TT>). Чтобы
поддержать отношения, в которых данный
объект представляет сторону «1» каждый
объект имеет также множество умных
указателей на экземпляры <TT CLASS="western">RelationObject</TT>
(поле <TT CLASS="western">master_relations_</TT>). 
</P>
<P>Класс <TT CLASS="western">RelationObject</TT> представляет
тот самый экземпляр отношения. Такие
объекты также всегда выделяются в куче
и не копируются. В них хранятся указатели
на связанные экземпляры <TT CLASS="western">DataObject</TT>:
один указатель на главный объект
отношения, и множество умных указателей
подчинённые. Таким образом они «владеют»
подчинёнными экземплярами <TT CLASS="western">DataObject</TT>,
а главные экземпляры <TT CLASS="western">DataObject</TT>
«владеют» (косвенно) всеми подчинёнными.
Обратите внимание, что для экземпляров
<TT CLASS="western">RelationObject</TT> также поддерживается
что-то вроде состояния, для реализации
ленивой загрузки. 
</P>
<P>Картинки: 
</P>
<IMG SRC="pics/Internals.1.ru.png" NAME="Pic1" ALIGN=BOTTOM WIDTH=1024 HEIGHT=552 BORDER=0>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
</BODY>
</HTML>
